package com.hulk.dryad.web.oauth2.config;

import com.hulk.dryad.common.constant.SecurityConstants;
import com.hulk.dryad.manage.security.component.PermitAllSecurityUrlProperties;
import com.hulk.dryad.manage.security.handler.FormAuthenticationFailureHandler;
import com.hulk.dryad.manage.security.handler.TenantSavedRequestAwareAuthenticationSuccessHandler;
import com.hulk.dryad.web.oauth2.basic.handler.DryadLoginSuccessHandler;
import com.hulk.dryad.web.oauth2.basic.mobile.MobileSecurityConfigurer;
import com.hulk.dryad.web.oauth2.basic.social.SocialSecurityConfigurer;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.firewall.StrictHttpFirewall;

/**
 * @author hulk
 * @date 2019/6/22 认证相关配置
 */
@Primary
@Order(90)
@Configuration
@EnableConfigurationProperties(PermitAllSecurityUrlProperties.class)
@RequiredArgsConstructor
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {

	private final PermitAllSecurityUrlProperties permitAllSecurityUrlProperties;

    @Override
    @SneakyThrows
    protected void configure(HttpSecurity http) {
        http.formLogin()
                .loginPage(SecurityConstants.LOGIN_PAGE)
                .loginProcessingUrl(SecurityConstants.LOGIN_PROCESSING_URL)
				.successHandler(tenantSavedRequestAwareAuthenticationSuccessHandler())
                .failureHandler(authenticationFailureHandler())
                .and()
                .logout()
                .logoutSuccessHandler((request, response, authentication) -> {
                    String referer = request.getHeader(HttpHeaders.REFERER);
                    response.sendRedirect(referer);
                }).deleteCookies("JSESSIONID").invalidateHttpSession(true)
                .and()
                .authorizeRequests()
                .antMatchers("/token/**", "/oauth/**", "/mobile/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .csrf().disable();
		http.cors().disable();
        http.apply(mobileSecurityConfigurer());
        http.apply(socialSecurityConfigurer());
    }


    /**
     * 不拦截静态资源
     *
     * @param web
     */
    @Override
    public void configure(WebSecurity web) {
		web.httpFirewall(new StrictHttpFirewall());
		web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**")
				.antMatchers(permitAllSecurityUrlProperties.getIgnoring().toArray(new String[0]));
    }
    /**
     * https://spring.io/blog/2017/11/01/spring-security-5-0-0-rc1-released#password-storage-updated
     * Encoded password does not look like BCrypt
     *
     * @return PasswordEncoder
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
    @Bean
    @Override
    @SneakyThrows
    public AuthenticationManager authenticationManagerBean() {
        return super.authenticationManagerBean();
    }
    @Bean
    public AuthenticationFailureHandler authenticationFailureHandler() {
        return new FormAuthenticationFailureHandler();
    }
    @Bean
    public AuthenticationSuccessHandler dryadLoginSuccessHandler() {
        return new DryadLoginSuccessHandler();
    }
	/**
	 * 具备租户传递能力
	 * @return AuthenticationSuccessHandler
	 */
	@Bean
	public AuthenticationSuccessHandler tenantSavedRequestAwareAuthenticationSuccessHandler() {
		return new TenantSavedRequestAwareAuthenticationSuccessHandler();
	}
	@Bean
	public MobileSecurityConfigurer mobileSecurityConfigurer() {
		return new MobileSecurityConfigurer();
	}
	@Bean
	public SocialSecurityConfigurer socialSecurityConfigurer() {
		return new SocialSecurityConfigurer();
	}




}
